/*
 * Fichier     : syntaxic.c
 * Version     : 1.0
 * Fonction    : <+FONCTION+>
 * Appel       : <+APPEL+>
 * Exit status : 0
 */
 
#define bool int
#define true 1
#define false 0

#include <stdio.h>
#include <stdlib.h>

#include <analex.h>
#include <string.h>
#include <symboles.h>

#include <gencod.h>

#include <postfix.c>

#define call(X) if(X()==false) return false
#define callp(X) if(X==false) return false

int const_type;

int u_type;
char u_lex[80];

int main_line;

/*
 * UtilisÃ© pour l'affichage dans aux
 * IncrÃ©mentÃ©e de 3 Ã  l'entrÃ©e de EXPR et TERM
 * DÃ©crÃ©mentÃ©e de 3 Ã  la sortie de EXPR et TERM
 */
int indent = 0;

bool lex_char(char* verif){

/*
 * Indentation utilisÃ© pour le fichier pgm/postfix
 * IncrÃ©mentÃ© de 3 Ã  l'entrÃ©e de EXPR et TERM
 * DÃ©crÃ©mentÃ© de Ã  la sortie de EXPR et TERM
 */
int indent = 0;

if(yylex()>0 && strcmp(u_lex, verif)==0){
		return true;
	} 
	return false;
}

bool lex_type(int z){
	if(yylex() == z){
		return true;
	}
	return false;
}

void error(char* location, char* attendu){
	fprintf(lstFic, "\n(EE)\nErreur ligne %u\n", ligne);
	fprintf(lstFic, "\t%s | attendu : '%s'\n", location, attendu);
	fprintf(lstFic, "\tLu : '%s'\n", u_lex);
	
	printf("\n(EE)\nErreur ligne %u\n", ligne);
	printf("\t%s | attendu : '%s'\n", location, attendu);
	printf("\tLu : '%s'\n", u_lex);
}

void error2(char* location, char* message){
	fprintf(lstFic, "\n(EE)\nErreur ligne %u\n", ligne);
	fprintf(lstFic, "\t%s | %s\n", location, message);
	
	printf("\n(EE)\nErreur ligne %u\n", ligne);
	printf("\t%s | %s\n", location, message);

}

void displayCharacter(FILE* f, const char* c, int nbr) {
	int i;
	for (i=0; i < nbr; i++) {
		fprintf(f, c);
	}
}

/*
 * Analyse d'un programme PASCAL
 * Diagramme de CONWAY : program->ident->en_tete->;->bloc->.
 */
bool program() {
	if(lex_char("program")==false){
		error("PROGRAM", "program");
		return false;
	}

	if(lex_type(IDENT)==false){
		//"PROGRAM | RAISON ERREUR"
		error("PROGRAM", "IDENT");
		return false;
	}
	
	u_type = yylex();
	
	call(en_tete);
	if(lex_char(";")==false){
		error("PROGRAM", ";");
		return false;
	}
	
	u_type = yylex();
	
	callp(bloc(1));

	if(lex_char(".")==false){
		error("PROGRAM", ".");
		return false;
	}
	
	codAppend(" #Fin du programne principal", codSTP());
	
	return true;
}


bool en_tete() {
	if(strcmp(u_lex,"(") != 0){
		error("EN_TETE", "(");
		return false;
	}
	
	strcpy(u_lex, ",");
	while(strcmp(u_lex,",")==0){
		if(lex_type(IDENT)==false){
			error("EN_TETE", "IDENT");
			return false;
		}
		yylex();
	}
	
	if(strcmp(u_lex,")")!=0){
		error("EN_TETE", ")");
		return false;
	}
	return true;
}

bool bloc(int main) {
	if(u_type==0){
		error("BLOC", "const || type || var || || function || procedure || begin");
		return false;
	}
	for (;;) {
		if(strcmp(u_lex, "const") == 0){
			u_type = yylex();
			call(consta);
		}else if(strcmp(u_lex, "var") == 0){
			u_type = yylex();
			call(dcl);
			main_line = codJMP();
		}else if(strcmp(u_lex, "procedure") == 0){
			call(methode);
		}else if(strcmp(u_lex, "begin") == 0){
			if(main==1){
				int l = codNOP();
				codAppend(" #Debut du programme principal", l);
				char c[32];
				sprintf(c, "%d #Saut vers programme principal", l);
				codAppend(c,main_line);
			}
			u_type = yylex();
															
			call(instr);
											
			if(strcmp(u_lex,";")==0) {
				while(strcmp(u_lex,";")==0){
					u_type = yylex();

					call(instr);
					
					if(strcmp(u_lex, "end") == 0) {return true;}
				}
			}

			if(strcmp(u_lex, "end") == 0) return true;
			else {
					error("BLOC", "; || end");
					return false;
			}
		} else {
			error("BLOC", "const || type || var || function || procedure || begin");
			return false;
		}
	}
}

bool consta(){
	char cname[80];

	for(;;) {
	

		if(u_type !=IDENT){
			error("CONST", "IDENT");
			return false;
		}
		
		if(symAdd(u_lex, 1) == ERR_REDEFINITION){  /* Ajout d'une constante */
				error2("CONST", "Identificateur dÃ©jÃ  utilisÃ©");
				return false;
			}
					
		strcpy(cname, u_lex);	
		if(strcmp(u_lex, "=")==0){
			error("CONST", "=");
			return false;
		}

		u_type = yylex();

		call(constante);
		
		switch(u_type){
			case CONST_ENTIER:{
				symSetConstEntier(atoi(u_lex));
				int l=codLIT(1, u_lex);
				codAppend(" #Constante ", l);
				codAppend(cname, l);
				break;
			}
			case CONST_REEL:{
				symSetConstReel(atof(u_lex));
				int l=codLIT(2, u_lex);
				codAppend(" #Constante ", l);
				codAppend(cname, l);
				break;
			}
			case CONST_BOOL:{
				int b = 1; if(strcmp(u_lex, "false")==0) {
					b = 0; strcpy(u_lex,"0");
				}else{
					strcpy(u_lex,"1");
				}
				symSetConstBool(b);
				int l=codLIT(3, u_lex);
				codAppend(" #Constante ", l);
				codAppend(cname, l);
				break;
			}
			case CONST_CHAR:{
				symSetConstChar(u_lex[1]);
				int l=codLIT(4, u_lex);
				codAppend(" #Constante ", l);
				codAppend(cname, l);
				break;
			}
			case CONST_CHAINE:{
				int l=codLIT(5, u_lex);
				codAppend(" #Constante ", l);
				codAppend(cname, l);
				u_lex[strlen(u_lex)-1]='\0';
				symSetConstChaine(u_lex+1);
				
				break;
			}
		}

		if(lex_char(";")==false){
			error("CONST", ";");	
			return false;
		}
		
		u_type = yylex();

		if((strcmp(u_lex,"type") == 0) || (strcmp(u_lex,"var") == 0) || 
		(strcmp(u_lex,"function") == 0) || (strcmp(u_lex,"procedure") == 0) 
		|| (strcmp(u_lex,"begin") == 0)) { 
			return true; 
		}
		if(u_type == IDENT){
			continue;
		}
	}
}

bool constante () {
	if(u_type == CONST_ENTIER) {const_type = 1;}
	else if(u_type == CONST_REEL) {const_type = 2;}
	else if(u_type == CONST_BOOL) {const_type = 3;} 
	else if(u_type == CONST_CHAR) {const_type = 4;}
	else if(u_type == CONST_CHAINE) {const_type = 5;}
	else {
		error("CONSTANTE", "CONSTANTE ENTIERE || CONSTANTE REELLE || CONSTANTE BOOLEENNE || CONSTANTE CARACTERE || CONSTANTE CHAINE");	
		return false;
	}
	return true;
}

bool type_dcl () {
		for(;;) {
		if(u_type == 0){
			error("TYPE_DCL", "IDENT");
			return false;
		}

		if(u_type !=IDENT){
			error("TYPE_DCL", "IDENT");
			return false;
		}

		yylex();

		if(strcmp(u_lex,",")==0) {
			while(strcmp(u_lex,",")==0){
				if(lex_type(IDENT)==false){
					error("TYPE_DCL", "IDENT");
					return false;
				}

				yylex();
			}
		}

		if(strcmp(u_lex,":")!=0){
			error("TYPE_DCL", ":");
			return false;
		}
		
		u_type = yylex();
		
		call(type_predefini);
		
		if(lex_char(";")==false){
			error("TYPE_DCL", ";");	
			return false;
		}
		
		u_type = yylex();

		if(strcmp(u_lex,"var")	== 0 || strcmp(u_lex,"function")	== 0 || strcmp(u_lex,"procedure")	== 0 || strcmp(u_lex,"begin")	== 0) { 
			return true; 
		}
		if(u_type == IDENT){
			continue;
		}
	}
}

bool dcl(){
	for(;;) {

		if(u_type !=IDENT){
			error("DCL", "IDENT");
			return false;
		}
		
		int i = 0;
		char tNom[80][80];
		
		strcpy(tNom[i++], u_lex); /*empilage des noms*/

		yylex();

		while(strcmp(u_lex,",")==0){
			if(lex_type(IDENT)==false){
				error("DCL", "IDENT");
				return false;
			}
			strcpy(tNom[i++], u_lex); /*empilage des noms*/

			yylex();
		}

		if(strcmp(u_lex,":")!=0){
			error("DCL", ":");
			return false;
		}
		
		u_type = yylex();
		
		call(type_predefini);
		
		int j=0, ret;
		while(j<i){ /* depilage des noms*/
			if(symAdd(tNom[j], 0) == ERR_REDEFINITION){
				error2("DCL", "Identificateur dÃ©jÃ  utilisÃ©");
				return false;
			}
			if(strcmp(u_lex,"integer")==0) {
				symSetVarEntier(0);
				int l=codINC(1,1);
				codAppend(" #Variable ", l);
				codAppend(tNom[j], l);
			}
			else if(strcmp(u_lex,"real")==0) {
				symSetVarReel(0);
				int l=codINC(2,1);
				codAppend(" #Variable ", l);
				codAppend(tNom[j], l);
			}
			else if(strcmp(u_lex,"boolean")==0) {
				symSetVarBool(0);
				int l=codINC(3,1);
				codAppend(" #Variable ", l);
				codAppend(tNom[j], l);
			}
			else if(strcmp(u_lex,"char")==0) {
				symSetVarChar(' ');
				int l=codINC(4,1);
				codAppend(" #Variable ", l);
				codAppend(tNom[j], l);
			}
			else if(strcmp(u_lex,"string")==0) {
				symSetVarChaine(" ");
				int l=codINC(5,1);
				codAppend(" #Variable ", l);
				codAppend(tNom[j], l);
			}
			
			++j;
		}
		
		if(lex_char(";")==false){
			error("DCL", ";");	
			return false;
		}
		
		u_type = yylex();

		if(strcmp(u_lex,"function")	== 0 || strcmp(u_lex,"procedure")	== 0 || strcmp(u_lex,"begin")	== 0) { 
			return true; 
		}
		if(u_type == IDENT){
			continue;
		} else {
			error("DCL", "function || procedure || begin");	
			return false;
		}
	}
}

bool type_predefini () {
	if(strcmp(u_lex,"integer")==0) {}
	else if(strcmp(u_lex,"real")==0) {}
	else if(strcmp(u_lex,"boolean")==0) {}
	else if(strcmp(u_lex,"char")==0) {}
	else if(strcmp(u_lex,"string")==0) {}
	else {
		error2("DCL", "Type inconnu. Reconnus : integer, real, boolean, char, string.");
		return false;
	}
	return true;
}

bool methode () {
	for(;;) {
		if(u_type == 0) {
			error("METHODE", "procedure");
			return false;
		}
		
		if(strcmp(u_lex,"function") == 0) {
			error("METHODE", "Fonctions non gÃ¨rÃ©es");
			return false;
			call(fonction);
			u_type = yylex();
		} else if(strcmp(u_lex,"procedure") == 0) {
			call(procedure);
		} else {
			error("METHODE", "procedure");
			return false;
		}
		
		if(strcmp(u_lex, ";") != 0) {
			error("METHODE", ";");
			return false;
		}
		
		u_type = yylex();
		
		callp(bloc(0));
		
		if(lex_char(";") == false) {
			error("METHODE", ";");
			return false;
		}
		
		codAppend(" #Retour de la procedure", codRET());
		
		u_type = yylex();
		
		if(strcmp(u_lex,"function") == 0 || strcmp(u_lex,"procedure") == 0 || strcmp(u_lex,"begin") == 0) {
			return true;
		}
		else if(strcmp(u_lex,";") == 0) {
			continue;
		}
		else {
			error("METHODE", "procedure || begin || ;");
			return false;
		}
	}
}

bool fonction () {
	if(strcmp(u_lex,"function") != 0) {
		error("FONCTION", "function");	
		return false;
	}
	
	if(lex_type(IDENT)==false){
		error("FONCTION", "IDENT");
		return false;
	}
	
	u_type = yylex();
	
	if(strcmp(u_lex,"(") == 0){
		call(param);
		u_type = yylex();
	}

	if(strcmp(u_lex,":") != 0) {
		error("FONCTION", ":");
		return false;
	}
									
	u_type = yylex();

	call(type_predefini);
		
	return true;
}

bool procedure () {
	if(strcmp(u_lex,"procedure") != 0) {
		error("PROCEDURE", "procedure");	
		return false;
	}
	
	
	if(lex_type(IDENT)==false){
		error("PROCEDURE", "IDENT");
		return false;
	}
	
	if(symExist(u_lex) || codProcGet(u_lex)!=-1){
		error2("PROCEDURE", "Identificateur dÃ©jÃ  utilisÃ©");
		return false;
	}
	
	int i=codNOP();
	codAppend(" #Code procedure ", i);
	codAppend(u_lex, i);
	
	codProcPush(u_lex, i);
	
	u_type = yylex();
	
	if(strcmp(u_lex,"(") == 0){
		call(param);
		u_type = yylex();
	}
		
	return true;
}

bool param() {
	if(strcmp(u_lex,"(") != 0){
		error("PARAM", "(");
		return false;
	}
	
	for(;;) {
		if(lex_type(IDENT)==false){
			error("PARAM", "IDENT");
			return false;
		}
		
		u_type = yylex();

		if(strcmp(u_lex,")") == 0) {
			break;
		}
		else if(strcmp(u_lex,",") == 0) {
		}
		else if(strcmp(u_lex,":") == 0 ){
			u_type = yylex();
			call(type_predefini);
			u_type = yylex();
			if(strcmp(u_lex,";") == 0) { continue; }
			else if(strcmp(u_lex,")") == 0) { break; }
			else {
				error("PARAM", ";");
				return false;
			}

		}
		else {
			error("PARAM", ", || :");
			return false;
		}
	}
	return true;
}

bool instr(){

	if(u_type == 0) {
		error("INSTR", "IDENT (affectation) || while || repeat || if || write || writeln || read || end");	
		return false;
	}
	if(strcmp(u_lex, "begin") == 0) {
		call(inst);
		u_type = yylex();
	} else if (strcmp(u_lex, "while") == 0) {
		call(While);
	} else if (strcmp(u_lex, "if") == 0) {
		call(If);
	} else if (strcmp(u_lex, "repeat") == 0) {
		call(repeat);
	} else if (strcmp(u_lex, "write") == 0) {
		call(write);
	} else if (strcmp(u_lex, "writeln") == 0) {
		call(writeln);
	} else if (strcmp(u_lex, "read") == 0) {
		call(read);
	} else if (strcmp(u_lex, "end") == 0) {
		return true;
	} else if (u_type == IDENT) {
	
		if(codProcGet(u_lex)!=-1){
			int l = codCAL(codProcGet(u_lex));
			codAppend(" #Appel procedure ", l);
			codAppend(u_lex, l);
			yylex();

			return true;
		}
		
		if(!symExist(u_lex)){
			char error_txt[80]; sprintf(error_txt, "identificateur '%s' introuvable.", u_lex);
			error2("TERME", error_txt);
			return false;
		}
		
		char var[80]; strcpy(var, u_lex);
		
		u_type = yylex();
		call(affectation);
		
		postfix(var);
		postfix(":=");
		if(symConst(var)==1){
			error2("TERME", "Affectation sur une constante");
			return false;
		}
		int l = codSTO(symType(var), symIndex(var));
		codAppend(" #Rangement dans variable ", l);
		codAppend(var, l);
		postfixEndLine();
	} 
	return true;
}

bool affectation() {
	if(u_type != OP_AFFECT) { 
		error("AFFECTATION", ":=");	
		return false;
	}

	call(expr);

	return true;
}

bool While () {
		int testl = codContent;
		call(cond);
		codSFL();
		
		int jmpl = codJPC();
		
		if(strcmp(u_lex,"do") != 0){
			error("WHILE", "do");
			return false;
		}
		u_type = yylex();
		call(instr);
		
		char app[32]; sprintf(app, "%d", testl);
		codAppend(app, codJMP());
		sprintf(app, "%d #Debut bloc while", codAppend(" #Fin bloc while", codNOP()));
		codAppend(app, jmpl);
		
		
					
		return true;
}

bool For () {

	if(lex_type(IDENT) == false) {
		error("FOR", "IDENT");
		return false;
	}

	u_type = yylex();
	call(affectation);

	if(strcmp(u_lex,"to") == 0) {}
	else if(strcmp(u_lex,"downto") == 0) {}
	else {
		error("FOR", "to || downto");
		return false;
	}

	u_type = yylex();
	call(constante);
	
	if(lex_char("do") == false) {
		error("FOR", "do || downto");
		return false;
	}
	
	u_type = yylex();
	
	call(instr);
	
	return true;
}

bool repeat () {
	u_type = yylex();
	
	int opl = codContent;
	call(instr);
	codAppend(" #Debut bloc repeat", opl);
	
	
	if (strcmp(u_lex, "until") != 0) {
		error("REPEAT", "until");
		return false;	
	}
	
	call(cond);
	codLIT(3, "0");
	codAppend(" #Inversion du resultat", codOPR(8));
	char jpl[80];
	sprintf(jpl, "%d #Retour bloc while", opl);
	codAppend(jpl, codJPC());
	
	return true;
}

bool If () {

	call(cond);
	
	codSFL();

	if(strcmp(u_lex,"then") != 0){
		error("IF", "then");
		return false;
	}
	
	int jpl = codJPC();
	
	u_type = yylex();

	call(instr);
	
	int l = codAppend(" #Fin bloc if", codNOP());
	char retl[32];
	sprintf(retl, "%d #Debut bloc if", l);
	codAppend(retl, jpl);

	if (strcmp(u_lex, ";") == 0)
		u_type = yylex();	

	if(strcmp(u_lex,"else") == 0) {
		u_type = yylex();
		call(instr);
		return true;
	}
	
	return true;
}

bool inst(){
	if(u_type == 0) {
		error("INST", "begin || rien");	
		return false;
	}
	
	for(;;){
		u_type = yylex();
		if(strcmp(u_lex,"end") != 0) {
				call(instr);
		}
		if(strcmp(u_lex, ";") == 0) continue;
		if(strcmp(u_lex, "end") == 0) {
			return true;
		}
		error("INST", "; || end");
		return false;
	}
}

bool expr(){
	u_type = yylex();

	if(u_type == 0) {
		error("EXPR", "TERME || '+' || '-'");	
		return false;
	}

	displayCharacter(aux, " ", indent);	
	fprintf(aux, "->EXPR\n");
	indent += 3;

	if(strcmp(u_lex,"+") == 0) {	
		u_type = yylex();
		displayCharacter(aux, " ", indent);
		fprintf(aux, "+\n");
		call(terme);
	 } else if(strcmp(u_lex,"-") == 0) {	
		u_type = yylex(); 
		displayCharacter(aux, " ", indent);
		fprintf(aux, "-\n");
		postfix("0");
		codLIT(1, "0");
		call(terme);
		postfix("-");
		codAppend(" # -",codOPR(1));
	}else{
		call(terme);
	}

	
								
	if(strcmp(u_lex,"+") == 0 || strcmp(u_lex,"-")==0) {

		while(strcmp(u_lex,"+") == 0 || strcmp(u_lex,"-")==0){
			 if(strcmp(u_lex,";") == 0) {
			 
                                break;
                        }

			char opr[2]; strcpy(opr, u_lex);
			
			displayCharacter(aux, " ", indent);
	        fprintf(aux, "%s\n", u_lex);

			u_type = yylex();
			call(terme);
			
			postfix(opr);
			if(opr[0]=='+')
				codAppend(" # +", codOPR(0));
			else
				codAppend(" # -", codOPR(1));
			
		}
	}

	indent -= 3;

	return true;
}

bool cond(){
	call(expr);
	codAppend(" #Condition", codContent-1);
	if(u_type == OP_BOOL) { }
	else {
		error("COND", "EXPR || OPERATEUR CONDITIONNEL");
		return false;
	}
	
	char opr[3]; strcpy(opr, u_lex);
	
	call(expr);
	
	postfix(opr);
	if(!strcmp(opr, "<"))
		codAppend(" # <", codOPR(4));
	else if(!strcmp(opr, "<="))
		codAppend(" # <=", codOPR(5));
	else if(!strcmp(opr, ">"))
		codAppend(" # >", codOPR(6));
	else if(!strcmp(opr, ">="))
		codAppend(" # >=", codOPR(7));
	else if(!strcmp(opr, "<>"))
		codAppend(" # <>", codOPR(8));
	else if(!strcmp(opr, "="))
		codAppend(" # =", codOPR(9));
		
	postfix("sfl");
	postfixEndLine();
	
	return true;
}

bool write(){
	if (strcmp(u_lex, "write") != 0) {
		error("WRITE", "WRITE");
		return false;
	}
	
	if(lex_char("(") == false) {
		error("WRITE", "(");
		return false;
	}
	
	u_type = yylex();
	if(!(u_type >= 1 && u_type <=5) && u_type != IDENT) {
		error("WRITE", "CONSTANTE || IDENT");
		return false;
	}
	
	if(u_type == IDENT && !symExist(u_lex)){
			error2("WRITE", "Identificateur non reconnu");
			return false;
		}
	
	if(u_type >= 1 && u_type <=5){
		codAppend(" #Chargement de literal pour write", codLIT(u_type, u_lex));
	}
	else {
		codAppend(" #Chargement de variable pour write", codLOD(symType(u_lex),symIndex(u_lex)));
	}
	
	codWRT();
	
	u_type = yylex();
	
	if(strcmp(u_lex,")") != 0) {
		error("WRITE", ")");
		return false;
	}
	
	
	
	u_type = yylex();
	
	return true;
}

bool writeln(){
	if (strcmp(u_lex, "writeln") != 0) {
		error("WRITELN", "WRITELN");
		return false;
	}
	
	u_type == yylex();
	if(strcmp(u_lex,";") == 0) {
		codAppend(" #Chargement de literal pour writeln", codLIT(5, "\"\""));
		codWRL();
		return true;
	}
	else if(strcmp(u_lex,"(") != 0) {
		error("WRITELN", "(");
		return false;
	}
	
	u_type = yylex();
	if(!(u_type >= 1 && u_type <=5) && u_type != IDENT) {
		
		error("WRITELN", "CONSTANTE || IDENT");
		return false;
	}
	
	if(u_type == IDENT && !symExist(u_lex)){
			error2("WRITELN", "Identificateur non reconnu.");
			return false;
		}
	
	if(u_type >= 1 && u_type <=5){
		codAppend(" #Chargement de literal pour writeln", codLIT(u_type, u_lex));
	}
	else {
		codAppend(" #Chargement de variable pour writeln", codLOD(symType(u_lex),symIndex(u_lex)));
	}
	
	codWRL();
	
	u_type = yylex();
	
	if(strcmp(u_lex,")") != 0) {
		error("WRITELN", ")");
		return false;
	}
	
	u_type = yylex();
	
	return true;
}

bool read(){
	if (strcmp(u_lex, "read") != 0) {
		error("READ", "READ");
		return false;
	}
	
	if(lex_char("(") == false) {
		error("READ", "(");
		return false;
	}
	
	u_type = yylex();
	if(u_type != IDENT) {
		error("READ", "IDENT");
		return false;
	}
	
	if(!symExist(u_lex)){
			error2("READ", "Identificateur non reconnu");
			return false;
	}
	
	if(symConst(u_lex)){
			error2("READ", "Read sur constante");
			return false;
	}
	
	codREA(symType(u_lex));
	codAppend(" #Rangement de variable depuis read", codSTO(symType(u_lex), symIndex(u_lex)));
	
	if(lex_char(")") == false) {
		error("READ", ")");
		return false;
	}
	
	u_type = yylex();
	
	return true;
}

bool readln(){
	if (strcmp(u_lex, "readln") != 0) {
		error("READLN", "READLN");
		return false;
	}
	
	u_type == yylex();
	if(strcmp(u_lex,";") == 0) {
		return true;
	}
	else if(strcmp(u_lex,"(") != 0) {
		error("READLN", "(");
		return false;
	}
	
	u_type = yylex();
	if(!(u_type >= 1 && u_type <=5) && u_type != IDENT) {
		error("READLN", "CONSTANTE || IDENT");
		return false;
	}
	
	if(lex_char(")") == false) {
		error("WRITE", ")");
		return false;
	}
	
	u_type = yylex();
	
	return true;
}

bool terme() {
	if(u_type == 0) {
		error("TERME", "'(' || IDENT || CONSTANTE || PROCEDURE");
		return false;
	}

	char opr = 0;
	
	for(;;){
		
	
		if(strcmp(u_lex,"(") == 0) {
			displayCharacter(aux, " ", indent);
			fprintf(aux, "->TERME\n");
			indent += 3;
			call(expr);
			if(strcmp(u_lex,")")!=0){
				error("TERME", ")");
				return false;
			}
			u_type = yylex();
		} else if(u_type == IDENT) {
			displayCharacter(aux, " ", indent);
	
			if(!symExist(u_lex)){
				char error_txt[80]; sprintf(error_txt, "Identificateur '%s' introuvable.", u_lex);
				error2("TERME", error_txt);
				return false;
			}
			int l = codLOD(symType(u_lex), symIndex(u_lex));
			codAppend(" #Chargement variable ", l);
			codAppend(u_lex, l);
			postfix(u_lex);
	
			fprintf(aux, "->TERME %s\n", u_lex);
			indent += 3;
			u_type =yylex();
		} else if(constante() == true) {
			displayCharacter(aux, " ", indent);
			fprintf(aux, "->TERME %s\n", u_lex);
			indent += 3;
			
			if(const_type == 3){
				if(strcmp(u_lex, "false")==0) strcpy(u_lex, "0");
				else if(strcmp(u_lex, "true")==0) strcpy(u_lex, "1");
				
			}
			codLIT(const_type, u_lex);
			postfix(u_lex);
			u_type = yylex();
		} else {
			error("TERME", "'(' || IDENT || CONSTANTE");
			return false;
		}
		
		if(opr !=0){
			char pr[2];
			pr[0] = opr; pr[1] = '\0';
			postfix(pr);
			if(opr == '*')
				codAppend(" # *", codOPR(2));
			else
				codAppend(" # /", codOPR(3));
			
		}
		
		if(strcmp(u_lex, "*") == 0 || strcmp(u_lex, "/") == 0){
			opr = u_lex[0];
			u_type = yylex();
		}else{
			break;
		}
	}

	indent -= 3;
	return true;
}

